{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "env: PYTORCH_ENABLE_MPS_FALLBACK=1\n"
     ]
    }
   ],
   "source": [
    "# For MacOS only\n",
    "%set_env PYTORCH_ENABLE_MPS_FALLBACK=1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Splines"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = np.linspace(0, 20, num=21)\n",
    "y = np.sin(x**2/3 + 4) + 2\n",
    "\n",
    "x_inter = np.linspace(0, 20, num=1001)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Cubic spline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy.interpolate import CubicSpline\n",
    "\n",
    "cubic_spline = CubicSpline(x, y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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8PfA34HE34Ngx99DTBRPEBEREVHvmLEjIiIicggGdkREREQOwcCOiIiIyCEY2BERERE5hOsCuz/96U8oLi5GUlISpk6dinfffbfH6zds2ICpU6ciKSkJw4YNw2OPPWbSSI3xwAMP4JxzzkF6ejry8vJwxRVXYN++fT3eZv369VAUpdOfzz77zKRR6+/+++/v9PMUFBT0eBunPReGDh3a5b/rnXfe2eX1TnkebNy4EYsWLUJRUREURcHLL7/c4fuqquL+++9HUVERkpOTceGFF+LTTz/t9X5XrVqFcePGITExEePGjcNLL71k0E+gj55+D21tbfjRj36EiRMnIjU1FUVFRbjxxhtx4sSJHu/z6aef7vI50tzcbPBPE5nengs333xzp59lxowZvd6vk54LALr8N1UUBb/+9a+7vc9Yey705b0xVl4bXBXY/eMf/8D3v/99/OQnP8GOHTtw/vnnY8GCBThy5EiX15eUlGDhwoU4//zzsWPHDvz4xz/Gd7/7Xaxatcrkketnw4YNuPPOO7F582asWbMG7e3tmDdvHhoaGnq97b59+1BaWqr9GTlypAkjNs748eM7/Dy7du3q9lonPhc++uijDj//mjVrAABXX311j7eL9edBQ0MDzj77bPzxj3/s8vu/+tWv8Nvf/hZ//OMf8dFHH6GgoABz587V9qzuyqZNm3DNNdfghhtuwMcff4wbbrgBX/3qV/Hhhx8a9WNEraffQ2NjI7Zv346f/vSn2L59O1588UV8/vnn+MpXvtLr/WZkZHR4fpSWliIpKcmIHyFqvT0XAGD+/PkdfpY33nijx/t02nMBQKd/zyeffBKKomDx4sU93m8sPRf68t4YM68NqotMnz5dvf322zt8bcyYMeq9997b5fX33HOPOmbMmA5f+9a3vqXOmDHDsDGarby8XAWgbtiwodtr1q1bpwJQT58+bd7ADLZ06VL17LPP7vP1bngufO9731OHDx+u+v3+Lr/vxOcBAPWll17S/u73+9WCggL1wQcf1L7W3NysZmZmqo899li39/PVr35VnT9/foevXXrppeq1116r+5iNcObvoStbtmxRAaiHDx/u9pqnnnpKzczM1HdwJunqd3DTTTepl19+eVj344bnwuWXX65efPHFPV4Ty88FVe383hhLrw2uydi1trZi27ZtmDdvXoevz5s3Dx988EGX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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots()\n",
    "ax.plot(x, y, 'o')\n",
    "ax.plot(x_inter, cubic_spline(x_inter), label='Spline')\n",
    "ax.legend(loc='best')\n",
    "\n",
    "plt.tight_layout()\n",
    "# plt.savefig('cubic_spline.png')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "\n",
    "from datasetsforecast.m3 import M3\n",
    "\n",
    "from utilsforecast.losses import mae, smape\n",
    "from utilsforecast.evaluation import evaluate\n",
    "\n",
    "from neuralforecast import NeuralForecast\n",
    "from neuralforecast.models import KAN, MLP, NBEATS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/marcopeix/miniconda3/envs/neuralforecast/lib/python3.10/site-packages/datasetsforecast/m3.py:108: FutureWarning: 'M' is deprecated and will be removed in a future version, please use 'ME' instead.\n",
      "  freq = pd.tseries.frequencies.to_offset(class_group.freq)\n",
      "INFO:lightning_fabric.utilities.seed:Seed set to 1\n",
      "INFO:lightning_fabric.utilities.seed:Seed set to 1\n",
      "INFO:lightning_fabric.utilities.seed:Seed set to 1\n",
      "INFO:pytorch_lightning.utilities.rank_zero:GPU available: True (mps), used: True\n",
      "INFO:pytorch_lightning.utilities.rank_zero:TPU available: False, using: 0 TPU cores\n",
      "INFO:pytorch_lightning.utilities.rank_zero:IPU available: False, using: 0 IPUs\n",
      "INFO:pytorch_lightning.utilities.rank_zero:HPU available: False, using: 0 HPUs\n",
      "INFO:pytorch_lightning.callbacks.model_summary:\n",
      "  | Name         | Type          | Params\n",
      "-----------------------------------------------\n",
      "0 | loss         | MAE           | 0     \n",
      "1 | padder_train | ConstantPad1d | 0     \n",
      "2 | scaler       | TemporalNorm  | 0     \n",
      "3 | layers       | ModuleList    | 276 K \n",
      "-----------------------------------------------\n",
      "276 K     Trainable params\n",
      "0         Non-trainable params\n",
      "276 K     Total params\n",
      "1.106     Total estimated model params size (MB)\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "1edc84cd045a4ceda557905f870d74a0",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Sanity Checking: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/marcopeix/dev/neuralforecast/neuralforecast/common/_scalers.py:30: UserWarning: The operator 'aten::nanmedian.dim_values' is not currently supported on the MPS backend and will fall back to run on the CPU. This may have performance implications. (Triggered internally at /Users/runner/work/_temp/anaconda/conda-bld/pytorch_1711403226260/work/aten/src/ATen/mps/MPSFallback.mm:13.)\n",
      "  x_median, _ = x_nan.nanmedian(dim=dim, keepdim=keepdim)\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "568a63d19249456096b2fe861fb78151",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Training: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "f88cb6aa2742485fbb283b1d1cfae5b5",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "56a3cfe0566641999cb0272811f21595",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "5386b8656f8b4466be2ee348f61916c9",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "7a33a630209a4763a15d6a2552b0847e",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "8887a551946d41f58e85f3fd44cbbbcb",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b189572c42ad4bd08a04bcf4f0240e6c",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "95ba7ba892b347869032d4917fc14973",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "70960ed00a2e461c919eeb72ab98f06f",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:pytorch_lightning.utilities.rank_zero:GPU available: True (mps), used: True\n",
      "INFO:pytorch_lightning.utilities.rank_zero:TPU available: False, using: 0 TPU cores\n",
      "INFO:pytorch_lightning.utilities.rank_zero:IPU available: False, using: 0 IPUs\n",
      "INFO:pytorch_lightning.utilities.rank_zero:HPU available: False, using: 0 HPUs\n",
      "INFO:pytorch_lightning.callbacks.model_summary:\n",
      "  | Name         | Type          | Params\n",
      "-----------------------------------------------\n",
      "0 | loss         | MAE           | 0     \n",
      "1 | padder_train | ConstantPad1d | 0     \n",
      "2 | scaler       | TemporalNorm  | 0     \n",
      "3 | mlp          | ModuleList    | 1.1 M \n",
      "4 | out          | Linear        | 18.4 K\n",
      "-----------------------------------------------\n",
      "1.1 M     Trainable params\n",
      "0         Non-trainable params\n",
      "1.1 M     Total params\n",
      "4.424     Total estimated model params size (MB)\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "38e44d87ebf54d13b61f8288320a5f01",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Sanity Checking: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "bb37bf685c9d4be1b43a462ae8654cd7",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Training: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "c675824ec58e4cfeaded816e1a1dba37",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b84de0aeeaf240e88945e7b1d9bf0731",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "71cf5223160b42f69e553aeffe0b2486",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "a9b676ee88cd4bc3af5995e53445e6a1",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "d0e530b459294e4aac4d23e399d0816c",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "be59cb74c3a84ca8acb5312251269129",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "315754ce1be2405784e5a62d20003e1d",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "4ac5e90e24f647dcad324bfb1b16b28e",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "d18051d87b8a4b3bb7e3ac0e2d74db53",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "1f6c5cd55cd5496297a7361553a0f80c",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:pytorch_lightning.utilities.rank_zero:`Trainer.fit` stopped: `max_steps=1000` reached.\n",
      "INFO:pytorch_lightning.utilities.rank_zero:GPU available: True (mps), used: True\n",
      "INFO:pytorch_lightning.utilities.rank_zero:TPU available: False, using: 0 TPU cores\n",
      "INFO:pytorch_lightning.utilities.rank_zero:IPU available: False, using: 0 IPUs\n",
      "INFO:pytorch_lightning.utilities.rank_zero:HPU available: False, using: 0 HPUs\n",
      "INFO:pytorch_lightning.callbacks.model_summary:\n",
      "  | Name         | Type          | Params\n",
      "-----------------------------------------------\n",
      "0 | loss         | MAE           | 0     \n",
      "1 | padder_train | ConstantPad1d | 0     \n",
      "2 | scaler       | TemporalNorm  | 0     \n",
      "3 | blocks       | ModuleList    | 2.5 M \n",
      "-----------------------------------------------\n",
      "2.5 M     Trainable params\n",
      "2.0 K     Non-trainable params\n",
      "2.5 M     Total params\n",
      "9.954     Total estimated model params size (MB)\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "d6d07cd178cb42ea8407bc61b1386202",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Sanity Checking: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "30aea9d05f75447c8b8a9db3ffefdad5",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Training: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "85a64887398b4509a1df54c809047e26",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "6734bbb167bd4adbb1886406e905a824",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "c04c43917f97462188d3a7908b44642d",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "8046be03d9724a238cd51ceff9178ef6",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "2e8feb432488416a81dd697a8ac9843d",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "5b02ba1a2ad646b4b49b7cc7fcb6b108",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "f0dcdcd6ed60460fb7320620af982f2c",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "a9df6e162f74495aad7f9efd5fab7b3d",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "6a426b5ca9b5492aa207afa7d528a8a5",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Validation: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/marcopeix/miniconda3/envs/neuralforecast/lib/python3.10/site-packages/utilsforecast/processing.py:362: FutureWarning: 'M' is deprecated and will be removed in a future version, please use 'ME' instead.\n",
      "  freq = pd.tseries.frequencies.to_offset(freq)\n",
      "/Users/marcopeix/miniconda3/envs/neuralforecast/lib/python3.10/site-packages/utilsforecast/processing.py:414: FutureWarning: 'M' is deprecated and will be removed in a future version, please use 'ME' instead.\n",
      "  freq = pd.tseries.frequencies.to_offset(freq)\n",
      "INFO:pytorch_lightning.utilities.rank_zero:Trainer already configured with model summary callbacks: [<class 'pytorch_lightning.callbacks.model_summary.ModelSummary'>]. Skipping setting a default `ModelSummary` callback.\n",
      "INFO:pytorch_lightning.utilities.rank_zero:GPU available: True (mps), used: True\n",
      "INFO:pytorch_lightning.utilities.rank_zero:TPU available: False, using: 0 TPU cores\n",
      "INFO:pytorch_lightning.utilities.rank_zero:IPU available: False, using: 0 IPUs\n",
      "INFO:pytorch_lightning.utilities.rank_zero:HPU available: False, using: 0 HPUs\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "5abaa2428af24221a6439ce7339a8458",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Predicting: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:pytorch_lightning.utilities.rank_zero:Trainer already configured with model summary callbacks: [<class 'pytorch_lightning.callbacks.model_summary.ModelSummary'>]. Skipping setting a default `ModelSummary` callback.\n",
      "INFO:pytorch_lightning.utilities.rank_zero:GPU available: True (mps), used: True\n",
      "INFO:pytorch_lightning.utilities.rank_zero:TPU available: False, using: 0 TPU cores\n",
      "INFO:pytorch_lightning.utilities.rank_zero:IPU available: False, using: 0 IPUs\n",
      "INFO:pytorch_lightning.utilities.rank_zero:HPU available: False, using: 0 HPUs\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "3e32c23f42934a6691042c8a047f72f9",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Predicting: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:pytorch_lightning.utilities.rank_zero:Trainer already configured with model summary callbacks: [<class 'pytorch_lightning.callbacks.model_summary.ModelSummary'>]. Skipping setting a default `ModelSummary` callback.\n",
      "INFO:pytorch_lightning.utilities.rank_zero:GPU available: True (mps), used: True\n",
      "INFO:pytorch_lightning.utilities.rank_zero:TPU available: False, using: 0 TPU cores\n",
      "INFO:pytorch_lightning.utilities.rank_zero:IPU available: False, using: 0 IPUs\n",
      "INFO:pytorch_lightning.utilities.rank_zero:HPU available: False, using: 0 HPUs\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "a4ae9b433f3c4b0aa06575a7c11f9d76",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Predicting: |          | 0/? [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/marcopeix/dev/neuralforecast/neuralforecast/core.py:198: FutureWarning: In a future version the predictions will have the id as a column. You can set the `NIXTLA_ID_AS_COL` environment variable to adopt the new behavior and to suppress this warning.\n",
      "  warnings.warn(\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>metric</th>\n",
       "      <th>KAN</th>\n",
       "      <th>MLP</th>\n",
       "      <th>NBEATS</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>mae</td>\n",
       "      <td>676.434965</td>\n",
       "      <td>652.624753</td>\n",
       "      <td>636.848956</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>smape</td>\n",
       "      <td>0.075452</td>\n",
       "      <td>0.071936</td>\n",
       "      <td>0.071063</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  metric         KAN         MLP      NBEATS\n",
       "0    mae  676.434965  652.624753  636.848956\n",
       "1  smape    0.075452    0.071936    0.071063"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Y_df, *_ = M3.load(\"./data\", \"Monthly\")\n",
    "\n",
    "horizon = 18\n",
    "\n",
    "test_df = Y_df.groupby('unique_id').tail(horizon)\n",
    "train_df = Y_df.drop(test_df.index).reset_index(drop=True)\n",
    "\n",
    "models = [\n",
    "    KAN(input_size=2*horizon,\n",
    "        h=horizon,\n",
    "        scaler_type='robust',\n",
    "        max_steps=1000,\n",
    "        early_stop_patience_steps=3),\n",
    "    MLP(input_size=2*horizon,\n",
    "        h=horizon,\n",
    "        scaler_type='robust',\n",
    "        max_steps=1000,\n",
    "        early_stop_patience_steps=3),\n",
    "    NBEATS(input_size=2*horizon,\n",
    "           h=horizon,\n",
    "           scaler_type='robust',\n",
    "           max_steps=1000,\n",
    "           early_stop_patience_steps=3)\n",
    "]\n",
    "\n",
    "nf = NeuralForecast(models=models, freq='M')\n",
    "\n",
    "nf.fit(train_df, val_size=horizon)\n",
    "\n",
    "preds = nf.predict()\n",
    "\n",
    "preds = preds.reset_index()\n",
    "\n",
    "test_df = pd.merge(test_df, preds, 'left', ['ds', 'unique_id'])\n",
    "\n",
    "evaluation = evaluate(\n",
    "    test_df,\n",
    "    metrics=[mae, smape],\n",
    "    models=[\"KAN\", \"MLP\", \"NBEATS\"],\n",
    "    target_col=\"y\",\n",
    ")\n",
    "\n",
    "evaluation = evaluation.drop(['unique_id'], axis=1).groupby('metric').mean().reset_index()\n",
    "evaluation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "neuralforecast",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
